<?php

/**
 * This file is part of the Codizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Codizer Core Team <team@codizer.org>
 * @package     Codizer
 */

class f_builder_ActionBuilder
{
	private $actionName;
	private $moduleName;
	private $actionPath;
	private $viewPath;
	private $templateDir;
	private $templateName;
	private $specialFields;
	private $fields;
	
	/**
	 * @return f_builder_ActionBuilder
	 */
	private function __construct()
	{		
		return $this;
	}
	
	/**
	 * Get instance
	 *
	 * @return f_builder_ActionBuilder
	 */
	public static function getInstance()
	{
		return new self();	
	}
	
	/**
	 * Set the module name to create the action in
	 *
	 * @param string $value
	 * @return f_builder_ActionBuilder
	 */
	public function setModuleName($value)
	{
		$this->moduleName = $value;
		return $this;
	}
	
	/**
	 * Set the action name to create
	 *
	 * @param string $value
	 * @return f_builder_ActionBuilder
	 */
	public function setActionName($value)
	{
		$args = explode("_", $value);
		if(count($args) > 1)
		{
			$args[count($args)-1] = ucfirst($args[count($args)-1]);
			$this->actionName = join("_", $args);
		}
		$this->actionName = $value;
		return $this;
	}

	/**
	 * Set the template name to create
	 *
	 * @param string $value
	 * @return f_builder_ActionBuilder
	 */
	public function setTemplateName($value)
	{
		$this->templateName = ucfirst($value);
		return $this;
	}
		
	/**
	 * Set the FieldsPopulator
	 *
	 * @param array $value
	 * @return f_builder_ActionBuilder
	 */	
	public function setFields($value)
	{
		$this->fields = $value;
		return $this;
	}
	
	/**
	 * Set specialFields
	 *
	 * @param array $value
	 * @return f_builder_ActionBuilder
	 */	
	public function setSpecialFields($value)
	{
		$this->specialFields = $value;
		return $this;
	}	
	
	/**
	 * Main method to build action and view
	 *
	 * @param string $basePath
	 */
	public function build($basePath = MODULES_DIR)
	{
		$this->templateDir = FRAMEWORK_HOME.DS."builder".DS."templates".DS;
		
		if($this->checkActionDirectory($basePath))
		{
			$actionName = str_replace("_", DS, $this->actionName);
			$actionFileName = $this->actionPath.DS.$actionName."Action.class.php";
			$actionContent = $this->getActionContent();
			$this->writeFile($actionFileName, $actionContent);
			
			$views = array("success", "error");
			
			foreach($views as $view)
			{
				$content = $this->getViewContent($view);
				$this->writeViewFile($view, $content);
			}			
		}
	}
	
	/**
	 * Main method to build Form action and view
	 *
	 * @param string $basePath
	 */
	public function buildForm($formName, $basePath = MODULES_DIR)
	{
		$this->templateDir = FRAMEWORK_HOME.DS."form".DS."templates".DS;
		
		if($this->checkActionDirectory($basePath))
		{
			$actionName = str_replace("_", DS, $this->actionName);
			$actionFileName = $this->actionPath.DS.$actionName."Action.class.php";
			$actionContent = $this->getFormActionContent($formName, $basePath);
			$this->writeFile($actionFileName, $actionContent, true);
			
			$views = array("success", "error");
			
			foreach($views as $view)
			{
				$content = $this->getFormViewContent($view);
				$this->writeViewFile($view, $content, true);
			}			
		}
	}
	
	
	/**
	 * Get empty action content
	 *
	 * @return string
	 */
	private function getActionContent()
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_Base.tpl";
		
		$template->setTemplate($templateFile)->disableCache();
		
		$className = "m_".$this->moduleName."_actions_".$this->actionName."Action";
		
		$template->assign("className", $className);
		
		return $template->render();
	}
	
	/**
	 * Get Form action content
	 *
	 * @param string $basePath
	 * @return string
	 */	
	private function getFormActionContent($formName, $basePath = MODULES_DIR)
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_Form.tpl";		
		$className = "m_".$this->moduleName."_actions_".$this->actionName."Action";	
		$object = "m_".$this->moduleName."_documents_".str_replace("block_Form","",$this->actionName);
				
		$template->setTemplate($templateFile)->disableCache();		
		$template->assign("className", $className);
		$template->assign("object", $object);
		$template->assign("formName", $formName);
		$template->assign("documentName", ucfirst($formName));
		$template->assign("moduleName", $this->moduleName);
		if(count($this->specialFields) > 0)
		{
			$template->assign("specialFields", serialize($this->specialFields));
		}
		
		return $template->render();
	}
	
	/**
	 * Get Form or List action content
	 *
	 * @param string $basePath
	 * @param string $type : "Form" or "List"
	 * @return string
	 */
	private function getFormOrListActionContent($basePath = MODULES_DIR)
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_Form.tpl";		
		$documentName = strtolower(str_replace("block_Form","",$this->actionName));
		$className = "m_".$this->moduleName."_actions_".$this->actionName."Action";	
		$object = "m_".$this->moduleName."_documents_".str_replace("block_Form","",$this->actionName);
				
		$template->setTemplate($templateFile)->disableCache();
				
		$fields = "$".$documentName."\n";
		$foreignFields = "\n";
		
		$relatedDocs = array();
		
		$condition = false;
		
		foreach($this->fieldsPopulator as $field)
		{
			if(!preg_match("#modules_(.*)/(.*)#", $field['type']))
			{
				$fields.= "\t\t\t\t\t->set".ucfirst($field['variable'])."(\$values['formValues']['".$field['variable']."'])\n";				
			}
			else
			{
				$foreignFields.= "\t\t\t\tif(\$values['formValues']['".$field['variable']."'] != \"\")\n";
				$foreignFields.= "\t\t\t\t{\n";
				$foreignFields.= "\t\t\t\t\t$".$documentName."->add".ucfirst($field['variable'])."ById(\$values['formValues']['".$field['variable']."']);\n";
				$foreignFields.= "\t\t\t\t}\n";
				
				$relatedDocs[$field['variable']]['foreignDoc'] = $field['foreignDoc'];
				
				$condition = true;
			}
		}
		
		$occurence = strrpos($fields,"\n");
		$tmp = substr($fields,0,$occurence);
		$fields = $tmp.";\n";
					
		$totalFields = $fields.$foreignFields;
		$totalFields.= "\n\t\t\t\t$".$documentName."->save();\n";
		
//		if($condition == true)
//		{
//			$file = $basePath.DS.$this->moduleName.DS."documents".DS.$documentName;
//			$template->assign("file", $file);
//		}
		$template->assign("className", $className);
		$template->assign("object", $object);
		$template->assign("fields", $totalFields);
		$template->assign("documentName", $documentName);
		$template->assign("moduleName", $this->moduleName);
		$template->assign("relatedDocs", $relatedDocs);
		
		return $template->render();
	}	
	
	
	/**
	 * Get view content in template by suffix
	 *
	 * @param string $suffix
	 * @return string
	 */
	private function getViewContent($suffix)
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_View.tpl";
		
		$template->setTemplate($templateFile)->disableCache();
		
		$className = "m_".$this->moduleName."_views_".$this->actionName.ucfirst($suffix)."View";
		
		$template->assign("className", $className);
		
		return $template->render();		
	}
	
	/**
	 * Get Form view content in template by suffix
	 *
	 * @param string $suffix

	 * @return string
	 */
	private function getFormViewContent($suffix)
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_View_Form.tpl";

		
		$template->setTemplate($templateFile)->disableCache();
		
		$className = "m_".$this->moduleName."_views_".$this->actionName.ucfirst($suffix)."View";
		
		$template->assign("className", $className);
		$template->assign("moduleName", $this->moduleName);
		$template->assign("templateName", $this->templateName);
		
		return $template->render();		
	}	
	
	/**
	 * Get Form or List view content in template by suffix
	 *
	 * @param string $suffix
	 * @param string $type : "Form" or "List"
	 * @return string
	 */
	private function getFormOrListViewContent($suffix, $type)
	{
		$template = f_template_Template::getInstance();

		$templateFile = $this->templateDir."action_View_Form.tpl";
		if($type == "List")
		{
			$templateFile = $this->templateDir."action_View_List.tpl";
		}
		
		$template->setTemplate($templateFile)->disableCache();
		
		$className = "m_".$this->moduleName."_views_".$this->actionName.ucfirst($suffix)."View";
		
		$template->assign("className", $className);
		$template->assign("moduleName", $this->moduleName);
		$template->assign("templateName", $this->templateName);
		
		return $template->render();		
	}	
	
	
	/**
	 * Write one view file
	 *
	 * @param string $suffix file suffix ex: Success, Input, etc...
	 * @param string $content
	 */
	private function writeViewFile($suffix, $content, $forceRewrite = false)
	{
		$actionName = str_replace("_", DS, $this->actionName);
		$viewFileName = $this->viewPath.DS.$actionName.ucfirst($suffix)."View.class.php";
		$this->writeFile($viewFileName, $content, $forceRewrite);
	}
	
	
	/**
	 * Check if the actions and views directory already exists in modules folders
	 *
	 * @param string $basePath
	 * @return boolean
	 */
	private function checkActionDirectory($basePath = MODULES_DIR)
	{
		$this->actionPath = $basePath.DS.$this->moduleName.DS."actions";
		$this->viewPath = $basePath.DS.$this->moduleName.DS."views";

		$actionPathOk = false;
		$viewPathOk = false;
		
		if(is_dir($this->actionPath) && is_dir($this->viewPath))
		{
			return true;
		}
		
		if(!is_dir($this->actionPath))
		{
			$actionPathOk = mkdir($this->actionPath, 0755, true);
		}
		if(!is_dir($this->viewPath))
		{
			$viewPathOk = mkdir($this->viewPath, 0755, true);
		}
		
		if($actionPathOk && $viewPathOk)
		{
			return true;
		}
		
		return false;
	}
	
	
	/**
	 * Write file
	 *
	 * @param string $fileName
	 * @param string $fileContent
	 */
	private function writeFile($fileName, $fileContent, $forceRewrite = false)
	{
		if($forceRewrite == false)
		{
			if(file_exists($fileName))
			{
				echo COLOR_RED."Skipped".COLOR_NORMAL." -> File ".$fileName." already exist, remove if necessary\n";
				return null;
			}
		}

		echo COLOR_GREEN."Writing".COLOR_NORMAL." -> ".$fileName."\n";
		
		$tmpPath = substr($fileName,0,strrpos($fileName,DS));
		
		if(is_dir($tmpPath) == false)
		{
			mkdir($tmpPath, 0775, true);
		}
		$fp = fopen($fileName, "w");
		fwrite($fp, $fileContent);
		fclose($fp);				
	}	
}